package com.love.cloud.common.excel.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.love.cloud.common.excel.bean.WriteHandlerBean;
import com.love.cloud.common.excel.callback.RepeatedWriteCallBack;
import org.apache.poi.ss.usermodel.Workbook;

import java.io.File;
import java.io.OutputStream;
import java.util.List;
import java.util.Set;

/**
 * EasyExcel的简单封装(写入excel工具类)
 * @author hongdongqu
 * @version 1.0
 */
public class WriteEasyExcelUtil {
    private final static String defaultSheetName="空";

    /**
     * 简单写入导出
     * @param targetPath 目标路径
     * @param fillData 填充的数据
     * @param templateBeanTypes 目标class类型
     * @param sheetName sheet页的名称
     */
    public static void simpleWriteExport(String targetPath, List fillData, Class templateBeanTypes, String sheetName){
        EasyExcel.write(targetPath,templateBeanTypes)
                .sheet(sheetName)
                .doWrite(fillData);
    }

    /**
     * 简单写入导出
     * @param targetOutputStream 目标输出流
     * @param fillData 填充的数据
     * @param templateBeanTypes 目标class类型
     * @param sheetName sheet页的名称
     */
    public static void simpleWriteExport(OutputStream targetOutputStream, List fillData, Class templateBeanTypes, String sheetName){
        EasyExcel.write(targetOutputStream,templateBeanTypes)
                .sheet(sheetName)
                .doWrite(fillData);
    }

    /**
     * 简单写入导出
     * @param targetPath 目标路径
     * @param fillData 填充的数据
     * @param templateBeanTypes 目标class类型
     * @param sheetName sheet页的名称
     * @param writeHandlerBean handle集合对象
     */
    public static void simpleWriteExport(String targetPath, List fillData, Class templateBeanTypes, String sheetName, WriteHandlerBean writeHandlerBean){
        ExcelWriter excelWriter = getExcelWriter(targetPath,templateBeanTypes);
        handleSimpleWriteExport(excelWriter,fillData,sheetName,writeHandlerBean);
    }

    /**
     * 简单写入导出
     * @param targetOutputStream 目标输出流
     * @param fillData 填充的数据
     * @param templateBeanTypes 目标class类型
     * @param sheetName sheet页的名称
     * @param writeHandlerBean handle集合对象
     */
    public static void simpleWriteExport(OutputStream targetOutputStream, List fillData, Class templateBeanTypes, String sheetName, WriteHandlerBean writeHandlerBean){
        ExcelWriter excelWriter = getExcelWriter(targetOutputStream,templateBeanTypes);
        handleSimpleWriteExport(excelWriter,fillData,sheetName,writeHandlerBean);
    }

    /**
     * 简单写入导出
     * @param targetPath 目标路径
     * @param excludeColumnFiledNames 排除导出字段名称
     * @param includeColumnFiledNames 只导出字段名称
     * @param fillData 填充的数据
     * @param templateBeanTypes 目标class类型
     * @param sheetName sheet页的名称
     */
    public static void simpleWriteExport(String targetPath, Set<String> excludeColumnFiledNames, Set<String> includeColumnFiledNames, List fillData, Class templateBeanTypes, String sheetName){
        EasyExcel.write(targetPath,templateBeanTypes)
                .excludeColumnFiledNames(excludeColumnFiledNames)
                .includeColumnFiledNames(includeColumnFiledNames)
                .sheet(sheetName)
                .doWrite(fillData);
    }


    /**
     * 简单写入导出
     * @param targetOutputStream 目标输出流
     * @param excludeColumnFiledNames 排除导出字段名称
     * @param includeColumnFiledNames 只导出字段名称
     * @param fillData 填充的数据
     * @param templateBeanTypes 目标class类型
     * @param sheetName sheet页的名称
     */
    public static void simpleWriteExport(OutputStream targetOutputStream, Set<String> excludeColumnFiledNames, Set<String> includeColumnFiledNames, List fillData, Class templateBeanTypes, String sheetName){
        EasyExcel.write(targetOutputStream,templateBeanTypes)
                .excludeColumnFiledNames(excludeColumnFiledNames)
                .includeColumnFiledNames(includeColumnFiledNames)
                .sheet(sheetName)
                .doWrite(fillData);
    }


    /**
     * 简单写入导出
     * @param targetOutputStream 目标输出流
     * @param excludeColumnFiledNames 排除导出字段名称
     * @param includeColumnFiledNames 只导出字段名称
     * @param fillData 填充的数据
     * @param templateBeanTypes 目标class类型
     * @param sheetName sheet页的名称
     * @param writeHandlerBean handle集合对象
     */
    public static void simpleWriteExport(OutputStream targetOutputStream, Set<String> excludeColumnFiledNames, Set<String> includeColumnFiledNames, List fillData, Class templateBeanTypes, String sheetName, WriteHandlerBean writeHandlerBean){
        ExcelWriter excelWriter = EasyExcel.write(targetOutputStream, templateBeanTypes)
                .excludeColumnFiledNames(excludeColumnFiledNames)
                .includeColumnFiledNames(includeColumnFiledNames)
                .build();
        handleSimpleWriteExport(excelWriter,fillData,sheetName,writeHandlerBean);
    }

    /**
     * 简单写入导出
     * @param targetPath 目标输出流
     * @param excludeColumnFiledNames 排除导出字段名称
     * @param includeColumnFiledNames 只导出字段名称
     * @param fillData 填充的数据
     * @param templateBeanTypes 目标class类型
     * @param sheetName sheet页的名称
     * @param writeHandlerBean handle集合对象
     */
    public static void simpleWriteExport(String targetPath, Set<String> excludeColumnFiledNames, Set<String> includeColumnFiledNames, List fillData, Class templateBeanTypes, String sheetName, WriteHandlerBean writeHandlerBean){
        ExcelWriter excelWriter = EasyExcel.write(targetPath, templateBeanTypes)
                .excludeColumnFiledNames(excludeColumnFiledNames)
                .includeColumnFiledNames(includeColumnFiledNames)
                .build();
        handleSimpleWriteExport(excelWriter,fillData,sheetName,writeHandlerBean);
    }

    /**
     * 执行简单导入
     * @param excelWriter
     * @param fillData
     * @param sheetName
     * @param writeHandlerBean
     */
    public static void handleSimpleWriteExport(ExcelWriter excelWriter, List fillData, String sheetName, WriteHandlerBean writeHandlerBean){
        try {
            WriteSheet writeSheet = EasyExcel.writerSheet(sheetName)
                    .registerWriteHandler(writeHandlerBean.getWorkbookWriteHandler())
                    .registerWriteHandler(writeHandlerBean.getSheetWriteHandler())
                    .registerWriteHandler(writeHandlerBean.getRowWriteHandler())
                    .registerWriteHandler(writeHandlerBean.getCellWriteHandler())
                    .build();
            excelWriter.write(fillData,writeSheet);
        }finally {
            // 千万别忘记finish 会帮忙关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

    /**
     * 重复写入数据
     * @param targetPath
     * @param templateBeanTypes
     * @param repeatedNum
     * @param repeatedWriteCallBack
     */
    public static void repeatedWriteExportByCustomize(String targetPath, Class templateBeanTypes, int repeatedNum, RepeatedWriteCallBack repeatedWriteCallBack){
        ExcelWriter excelWriter = getExcelWriter(targetPath, templateBeanTypes);
        handleRepeatedWrite(excelWriter,repeatedNum,repeatedWriteCallBack);
    }

    /**
     * 重复写入数据
     * @param targetOutputStream
     * @param templateBeanTypes
     * @param repeatedNum
     * @param repeatedWriteCallBack
     */
    public static void repeatedWriteExportByCustomize(OutputStream targetOutputStream, Class templateBeanTypes, int repeatedNum, RepeatedWriteCallBack repeatedWriteCallBack){
        ExcelWriter excelWriter = getExcelWriter(targetOutputStream, templateBeanTypes);
        handleRepeatedWrite(excelWriter,repeatedNum,repeatedWriteCallBack);
    }


    /**
     * 重复写入数据
     * @param targetPath
     * @param fillData
     * @param templateBeanTypes
     * @param sheetName
     * @param writeHandlerBean
     * @param repeatedNum
     */
    public static void repeatedWriteExport(String targetPath, List fillData, Class templateBeanTypes, String sheetName, WriteHandlerBean writeHandlerBean, int repeatedNum){
        repeatedWriteExportByCustomize(targetPath, templateBeanTypes, repeatedNum,new RepeatedWriteCallBack() {
            @Override
            public WriteSheet createDefaultSheet() {
                return EasyExcel.writerSheet(sheetName)
                        .registerWriteHandler(writeHandlerBean.getWorkbookWriteHandler())
                        .registerWriteHandler(writeHandlerBean.getSheetWriteHandler())
                        .registerWriteHandler(writeHandlerBean.getRowWriteHandler())
                        .registerWriteHandler(writeHandlerBean.getCellWriteHandler())
                        .build();
            }

            @Override
            public void excelWriteHandler(int index, ExcelWriter excelWriter, WriteSheet writeSheet) {
                //此方法只是不停添加
                excelWriter.write(fillData, writeSheet);
            }
        });
    }

    /**
     * 处理重复写入的执行方法
     * @param excelWriter excel写入器
     * @param repeatedNum 重复次数
     * @param repeatedWriteCallBack 回调接口
     */
    public static void handleRepeatedWrite(ExcelWriter excelWriter, int repeatedNum, RepeatedWriteCallBack repeatedWriteCallBack){
        try{
            // 这里注意 如果同一个sheet只要创建一次
            WriteSheet writeSheet =repeatedWriteCallBack.createDefaultSheet();
            //根据传入的次数来执行
            for (int i = 0; i < repeatedNum; i++) {
                //统一执行回调中的方法
                repeatedWriteCallBack.excelWriteHandler(i,excelWriter,writeSheet);
            }
            Workbook workbook = excelWriter.writeContext().writeWorkbookHolder().getWorkbook();
            // 设置强制计算公式：不然公式会以字符串的形式显示在excel中
            workbook.setForceFormulaRecalculation(true);
        }finally {
            // 千万别忘记finish 会帮忙关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

    /**
     * 填充数据导出（无handle）
     * @param targetPath 目标路径
     * @param templateFile 模板文件对象
     * @param fillData 填充数据
     */
    public static void fillDataToExport(String targetPath, File templateFile, Object fillData){
        fillDataToExport(targetPath,templateFile,fillData,new WriteHandlerBean());
    }

    /**
     * 填充数据导出（有handle）
     * @param targetPath 目标路径
     * @param templateFile 模板文件对象
     * @param fillData 填充数据
     * @param writeHandlerBean handle集合对象
     */
    public static void fillDataToExport(String targetPath, File templateFile, Object fillData, WriteHandlerBean writeHandlerBean){
        //默认当前页标签为第一页
        fillDataToExport(targetPath,templateFile,fillData,defaultSheetName,writeHandlerBean);
    }

    /**
     * 填充数据导出（有handle，可设置sheetName）
     * @param targetPath 目标路径
     * @param templateFile 模板文件对象
     * @param fillData 填充数据
     * @param sheetName sheet页名称
     * @param writeHandlerBean handle集合对象
     */
    public static void fillDataToExport(String targetPath, File templateFile, Object fillData, String sheetName, WriteHandlerBean writeHandlerBean){
        ExcelWriter excelWriter =getExcelWriter( targetPath,templateFile);
        handlefillData(excelWriter,fillData,sheetName,writeHandlerBean);
    }


    /**
     * 目标文件是输出流
     * 填充数据导出（无handle，默认sheetName为0）
     * @param targetOutputStream 目标输出流
     * @param templateFile 模板文件对象
     * @param fillData 填充数据
     */
    public static void fillDataToExport(OutputStream targetOutputStream, File templateFile, Object fillData){
        fillDataToExport(targetOutputStream,templateFile,fillData,new WriteHandlerBean());
    }

    /**
     * 目标文件是输出流
     * 填充数据导出（有handle）
     * @param targetOutputStream 目标输出流
     * @param templateFile 模板文件对象
     * @param fillData 填充数据
     * @param writeHandlerBean handle集合对象
     */
    public static void fillDataToExport(OutputStream targetOutputStream, File templateFile, Object fillData, WriteHandlerBean writeHandlerBean){
        //默认当前页标签为第一页
        fillDataToExport(targetOutputStream,templateFile,fillData,defaultSheetName,writeHandlerBean);
    }

    /**
     * 目标文件是输出流
     * 填充数据导出（有handle，可设置sheetName）
     * @param targetOutputStream 目标输出流
     * @param templateFile 模板文件对象
     * @param fillData 填充数据
     * @param sheetName sheet页名称
     * @param writeHandlerBean handle集合对象
     */
    public static void fillDataToExport(OutputStream targetOutputStream, File templateFile, Object fillData, String sheetName, WriteHandlerBean writeHandlerBean){
        ExcelWriter excelWriter =getExcelWriter( targetOutputStream,templateFile);
        handlefillData(excelWriter,fillData,sheetName,writeHandlerBean);
    }

    /**
     * 处理填充数据
     * @param excelWriter excel写入对象
     * @param fillData 填充数据
     * @param sheetName sheet页名称
     * @param writeHandlerBean handle集合对象
     */
    public static void handlefillData(ExcelWriter excelWriter, Object fillData, String sheetName, WriteHandlerBean writeHandlerBean){
        try {
            WriteSheet writeSheet = EasyExcel.writerSheet(sheetName)
                    .registerWriteHandler(writeHandlerBean.getWorkbookWriteHandler())
                    .registerWriteHandler(writeHandlerBean.getSheetWriteHandler())
                    .registerWriteHandler(writeHandlerBean.getRowWriteHandler())
                    .registerWriteHandler(writeHandlerBean.getCellWriteHandler())
                    .build();
            //首次填充列表数据
            excelWriter.fill(fillData, FillConfig.builder().forceNewRow(Boolean.TRUE).build(), writeSheet);
            Workbook workbook = excelWriter.writeContext().writeWorkbookHolder().getWorkbook();
            // 设置强制计算公式：不然公式会以字符串的形式显示在excel中
            workbook.setForceFormulaRecalculation(true);
        }finally{
            // 千万别忘记关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }

    }

    /**
     * 获取到Excel写入对象
     * @param targetOutputStream 目标输出流
     * @param templateFile 模板文件对象
     * @return
     */
    public static ExcelWriter getExcelWriter(OutputStream targetOutputStream, File templateFile){
        return EasyExcel.write(targetOutputStream).withTemplate(templateFile).build();
    }

    /**
     * 获取到Excel写入对象
     * @param targetOutputStream 目标输出流
     * @return
     */
    public static ExcelWriter getExcelWriter(OutputStream targetOutputStream){
        return EasyExcel.write(targetOutputStream).build();
    }

    /**
     * 获取到Excel写入对象
     * @param targetPath 目标文件的路径
     * @param templateFile 模板文件对象
     * @return
     */
    public static ExcelWriter getExcelWriter(String targetPath, File templateFile){
        return EasyExcel.write(targetPath).withTemplate(templateFile).build();
    }

    /**
     * 获取到Excel写入对象
     * @param targetPath 目标文件的路径
     * @return
     */
    public static ExcelWriter getExcelWriter(String targetPath){
        return EasyExcel.write(targetPath).build();
    }

    /**
     * 获取到Excel写入对象
     * @param targetPath 目标文件的路径
     * @param targetType 目标class类型
     * @return
     */
    public static ExcelWriter getExcelWriter(String targetPath, Class targetType){
        return EasyExcel.write(targetPath,targetType).build();
    }

    /**
     * 获取到Excel写入对象
     * @param targetOutputStream 目标输出流
     * @param targetType 目标class类型
     * @return
     */
    public static ExcelWriter getExcelWriter(OutputStream targetOutputStream, Class targetType){
        return EasyExcel.write(targetOutputStream,targetType).build();
    }


}
